package configrations

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"go.yaml.in/yaml/v2"
)

const (
	DEV_CONFIG_FILE_NAME  = "dev.yaml"
	PROC_CONFIG_FILE_NAME = "prod.yaml"
)

type ConfigLoader struct {
	configDir string
}

type LoadOptions struct {
	configDir string
	debugMode bool
}

type LoadOption func(*LoadOptions)

func WithConfigDir(configDir string) LoadOption {
	return func(opts *LoadOptions) {
		opts.configDir = configDir
	}
}

func WithDebugMode(debugMode bool) LoadOption {
	return func(opts *LoadOptions) {
		opts.debugMode = debugMode
	}
}

func NewBasicConfigLoader(configDir string) *ConfigLoader {
	return &ConfigLoader{
		configDir: configDir,
	}
}

func (cl *ConfigLoader) LoadBasicConfig(opts ...LoadOption) (*BasicConfig, error) {
	options := &LoadOptions{
		configDir: cl.configDir,
		debugMode: false,
	}

	for _, opt := range opts {
		opt(options)
	}

	// 根据debug模式选择配置文件
	filename := DEV_CONFIG_FILE_NAME
	if !options.debugMode {
		filename = PROC_CONFIG_FILE_NAME
	}

	configPath := filepath.Join(options.configDir, filename)

	// 检查文件是否存在
	if _, err := os.Stat(configPath); os.IsNotExist(err) {
		return nil, fmt.Errorf("config file not found: %s", configPath)
	}

	// 读取配置文件
	bytes, err := os.ReadFile(configPath)
	if err != nil {
		return nil, fmt.Errorf("read config file failed: %w", err)
	}

	// 解析YAML
	var config BasicConfig
	if err := yaml.Unmarshal(bytes, &config); err != nil {
		return nil, fmt.Errorf("unmarshal yaml config failed: %w", err)
	}

	return &config, nil
}

func LoadConfigFromFile[T any](filepath string) (*T, error) {
	var cfg T
	bytes, err := os.ReadFile(filepath)
	if err != nil {
		return nil, fmt.Errorf("read config file failed: %w", err)
	}
	switch {
	case strings.HasSuffix(filepath, ".yaml") || strings.HasSuffix(filepath, ".yml"):
		if err := yaml.Unmarshal(bytes, &cfg); err != nil {
			return nil, fmt.Errorf("unmarshal yaml config failed: %w", err)
		}
	case strings.HasSuffix(filepath, ".json"):
		if err := yaml.Unmarshal(bytes, &cfg); err != nil {
			return nil, fmt.Errorf("unmarshal json config failed: %w", err)
		}
	default:
		return nil, fmt.Errorf("unsupported config file format: %s", filepath)
	}
	return &cfg, nil
}
